﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Renci.Data.Interop.OpenGIS;
using Renci.Data.Interop.OpenGIS.Om_10;
using Renci.Data.Interop.OpenGIS.SensorML_101;
using Renci.Data.Interop.OpenGIS.Sos_10;

namespace Renci.Ogc.Client
{
    /// <summary>
    /// Represent SOS client
    /// </summary>
    public class SosClient
    {
        /// <summary>
        /// Gets or sets service server URI.
        /// </summary>
        /// <value>The server URI.</value>
        public Uri ServerUri { get; protected set; }

        /// <summary>
        /// Gets or sets service version.
        /// </summary>
        /// <value>The version.</value>
        public string Version { get; protected set; }

        /// <summary>
        /// Internal reference to SweClient object
        /// </summary>
        private SweClient _client;

        public SosClient(Uri uri, string version)
        {
            this.ServerUri = uri;
            this.Version = version;
            this._client = new SweClient(uri);
        }

        /// <summary>
        /// Performs service GetCapabilities request
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Service capabilities</returns>
        public Renci.Data.Interop.OpenGIS.Sos_10.Capabilities GetCapabilities(GetCapabilities request)
        {
            Renci.Data.Interop.OpenGIS.Sos_10.Capabilities response;

            this._client.HandlePostRequest("SOS", "GetCapabilities", this.Version, request, out response);

            return response;
        }

        /// <summary>
        /// Performs service GetCapabilities request
        /// </summary>
        /// <returns></returns>
        public Renci.Data.Interop.OpenGIS.Sos_10.Capabilities GetCapabilities()
        {
            return this.GetCapabilities(null, null, null, null);
        }

        /// <summary>
        /// Performs service GetCapabilities request
        /// </summary>
        /// <returns></returns>
        public Renci.Data.Interop.OpenGIS.Sos_10.Capabilities GetCapabilities(ReadOnlyCollection<string> acceptVersions, ReadOnlyCollection<string> sections, string updateSequence, ReadOnlyCollection<string> acceptFormats)
        {
            Renci.Data.Interop.OpenGIS.Sos_10.Capabilities response;

            Dictionary<string, string> parameters = new Dictionary<string, string>();
            if (acceptVersions != null)
            {
                parameters.Add("AcceptVersions", string.Join(",", acceptVersions.ToArray()));
            }
            if (sections != null)
            {
                parameters.Add("Sections", string.Join(",", sections.ToArray()));
            }
            if (updateSequence != null)
            {
                parameters.Add("updateSequence", updateSequence);
            }
            if (acceptFormats != null)
            {
                parameters.Add("AcceptFormats", string.Join(",", acceptFormats.ToArray()));
            }

            this._client.HandleGetRequest("SOS", "GetCapabilities", this.Version, parameters, out response);

            return response;
        }

        /// <summary>
        /// Performs service DescribeSensor request
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Sensor description</returns>
        public Sensor DescribeSensor(DescribeSensor request)
        {
            Sensor response;

            this._client.HandlePostRequest("SOS", "DescribeSensor", this.Version, request, out response);

            return response;
        }

        /// <summary>
        /// Performs service DescribeSensor request
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Sensor description</returns>
        public Sensor DescribeSensor(string outputFormat, string procedure)
        {
            if (string.IsNullOrEmpty(procedure))
            {
                throw new ArgumentNullException("outputFormat");
            }
            if (string.IsNullOrEmpty(procedure))
            {
                throw new ArgumentNullException("procedure");
            }

            Sensor response;

            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("OutputFormat", outputFormat);
            parameters.Add("procedure", procedure);

            this._client.HandleGetRequest("SOS", "DescribeSensor", this.Version, parameters, out response);

            return response;
        }

        /// <summary>
        /// Performs service GetObservation request
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>The observation</returns>
        public ObservationCollectionType GetObservation(GetObservation request)
        {
            ObservationCollectionType response;

            this._client.HandlePostRequest("SOS", "GetObservation", this.Version, request, out response);

            return response;
        }
                /// <summary>
        /// Performs service GetObservation request
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>The observation</returns>
        public ObservationCollectionType GetObservation(string offering, string responseFormat, string observedProperty, ResponseModeType responseMode)
        {
            if (string.IsNullOrEmpty(offering))
            {
                throw new ArgumentNullException("offering");
            }
            if (string.IsNullOrEmpty(responseFormat))
            {
                throw new ArgumentNullException("responseFormat");
            }
            if (string.IsNullOrEmpty(observedProperty))
            {
                throw new ArgumentNullException("observedProperty");
            }

            ObservationCollectionType response;

            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("offering", offering);
            parameters.Add("responseFormat", responseFormat);
            parameters.Add("observedProperty", observedProperty);
            parameters.Add("responseMode", responseMode.ToStringValue());

            this._client.HandleGetRequest("SOS", "GetObservation", this.Version, parameters, out response);

            return response;
        }
    }
}
